
package com.seekting.gongzhu.serversdk;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.seekting.gongzhu.sdk.ConnectListener;
import com.seekting.gongzhu.sdk.Connectedable;
import com.seekting.gongzhu.sdk.IRule;
import com.seekting.gongzhu.sdk.KLog;
import com.seekting.gongzhu.sdk.gson.AJson;
import com.seekting.gongzhu.sdk.gson.GsonConverter;
import com.seekting.gongzhu.sdk.gson.GsonHolder;
import com.seekting.gongzhu.sdk.gson.s2c.PlayerJsonS;
import com.seekting.gongzhu.sdk.gson.s2c.PrepareJsonS;

public class GGame extends HostGame {

    private Status status;
    private PlayerJsonS[] players;
    private Connectedable connectedable;
    private ConnectListener mConnectListener;
    private IRule mRuleImpl;

    private Map<String, HostCommond> actionList;

    public GGame() {
        actionList = new HashMap<String, HostCommond>();
        players = new PlayerJsonS[getMaxJoinSize()];
        mRuleImpl = new GRuleImpl();
        status = Status.NotCreate;

    }

    @Override
    public synchronized void create(Connectedable connectedable) {
        status = Status.Create;
        this.connectedable = connectedable;
        mConnectListener = new MyConnectedListener(this);
        this.connectedable.bind(mConnectListener);

    }

    @Override
    public synchronized void start() {
        status = Status.Start;
    }

    @Override
    public synchronized void reStart() {
    }

    @Override
    public synchronized void exit() {
        if (connectedable != null) {
            connectedable.unBind(mConnectListener);
        }
    }

    @Override
    public int getMaxJoinSize() {
        return 4;
    }

    @Override
    public synchronized void onJoin(String ip) {
        KLog.e("joinGame" + ip);
        PlayerJsonS playerJsons = new PlayerJsonS(ip);
        playerJsons.setStatus(PlayerJsonS.Status.Joined);

        int position = getEmptyPosition();
        if (position > -1) {
            players[position] = playerJsons;
            PrepareJsonS prepareJsonS = new PrepareJsonS();
            prepareJsonS.setPosition(position);
            prepareJsonS.setPlayers(players);
            for (PlayerJsonS playerJsonS2 : players) {
                if (playerJsonS2 != null) {
                    send(playerJsonS2.getIp(), prepareJsonS);
                }
            }
        }
    }

    private int getEmptyPosition() {
        for (int i = 0; i < players.length; i++) {
            if (players[i] == null) {
                return i;
            }
        }
        return -1;
    }

    private synchronized void send(String ip, AJson actionGson) {
        GsonHolder g = new GsonHolder(actionGson);
        String str = GsonConverter.convertStr(g);
        connectedable.send(ip, str);
    }

    @Override
    public synchronized void onLeave(int position, String ip) {

        KLog.e("levaeGame");
        if (position >= 0 && position < players.length) {

            players[position] = null;
        }
        setCanStart(false);
    }

    @Override
    public synchronized boolean canJoin() {
        return status == Status.Create;
    }

    @Override
    public synchronized boolean isJoined(String ip) {
        // return players.containsKey(ip);
        return false;
    }

    @Override
    public synchronized void onReceive(String ip, String str) {

    }

    private enum Status {
        NotCreate, Create, Start;
    }

    private static class MyConnectedListener implements ConnectListener {

        private Joinedable joinedable;

        public MyConnectedListener(Joinedable joinedable) {

            this.joinedable = joinedable;
        }

        @Override
        public void onDisConnect(int index, String ipPort) {
            if (joinedable != null) {
                joinedable.onLeave(index, ipPort);
            }
        }

        @Override
        public ConnectResult tryConnect(String ipPort) {
            if (joinedable == null) {
                return ConnectResult.FailNoGameJoin;
            }
            if (!joinedable.canJoin()) {
                return ConnectResult.FailNoEmptyPosition;
            }
            if (joinedable.isJoined(ipPort)) {
                return ConnectResult.FailDuplicateJoin;
            }
            return ConnectResult.Success;
        }

        @Override
        public void ConnectSuc(String ipPort) {
            joinedable.onJoin(ipPort);
        }

    }

    private synchronized boolean isAllPrepared() {
        for (PlayerJsonS playerJsonS : players) {
            if (playerJsonS.getStatus() != PlayerJsonS.Status.Prepared) {
                return false;
            }
        }
        return true;

    };

    private synchronized void checkCanStart() {

        setCanStart(isAllPrepared());

    };

    private void setCanStart(boolean start) {
        if (start) {
            KLog.d("可以开始啦!");
            start();
        }
    }

    @Override
    public synchronized void onPrepareStateChange(int index, boolean prepared, String ip) {
        if (index >= 0 && index < players.length) {
            PlayerJsonS playerInServer = players[index];
            PlayerJsonS.Status status = prepared ? PlayerJsonS.Status.Prepared
                    : PlayerJsonS.Status.Joined;
            playerInServer.setStatus(status);
            checkCanStart();
        }
    }

}
